#ifndef BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_
#define BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_

namespace base
{
	template <typename Interface> class rcsf_ptr;

	
	template <typename Interface>
	class ReferenceCountedSingletonFactory
	{
		friend class rcsf_ptr<Interface>;
	public:
		ReferenceCountedSingletonFactory() : ref_count_(0) {}

		virtual ~ReferenceCountedSingletonFactory()
		{
			ASSERT(ref_count_ == 0);
		}

	protected:
		// Must be implemented in a sub-class.
		virtual bool SetupInstance() = 0;
		virtual void CleanupInstance() = 0;

		scoped_ptr<Interface> instance_;

	private:
		Interface* GetInstance()
		{
			CritScope(&crit_);
			if (ref_count_ == 0)
			{
				if (!SetupInstance())
				{
					LOG(LS_ERROR) << "Failed to setup instance";
					return NULL;
				}
				ASSERT(instance_.get() != NULL);
			}
			++ref_count_;

			LOG(LS_VERBOSE) << "Number of  references: " << ref_count_;
			return instance_.get();
		}

		void ReleaseInstance()
		{
			CritScope cs(&crit_);
			ASSERT(ref_count_ > 0);
			ASSERT(instance_.get() != NULL);
			--ref_count_;
			LOG(LS_VERBOSE) << "Number of  references: " << ref_count_;
			if (ref_count_ == 0)
				CleanupInstance();
		}

		CriticalSection crit_;
		int ref_count_;

		DISALLOW_COPY_AND_ASSIGN(ReferenceCountedSingletonFactory);
	};

	template <typename Interface>
	class rcsf_ptr
	{
	public:
		// Create a pointer that uses the factory to get the instance.
		// This is lazy - it won't generate the instance until it is requested.
		explicit rcsf_ptr(ReferenceCountedSingletonFactory<Interface>* factory)
			: instance_(NULL), factory_(factory)
		{
		}

		~rcsf_ptr()
		{
			release();
		}

		Interface& operator*()
		{
			EnsureAcquired();
			return *instance_;
		}

		Interface* operator->()
		{
			EnsureAcquired();
			return instance_;
		}

		// Gets the pointer, creating the singleton if necessary. May return NULL if
		// creation failed.
		Interface* get()
		{
			Acquire();
			return instance_;
		}

		// Set instance to NULL and tell the factory we aren't using the instance
		// anymore.
		void release()
		{
			if (instance_)
			{
				instance_ = NULL;
				factory_->ReleaseInstance();
			}
		}

		// Lets us know whether instance is valid or not right now.
		// Even though attempts to use the instance will automatically create it, it
		// is advisable to check this because creation can fail.
		bool valid() const
		{
			return instance_ != NULL;
		}

		// Returns the factory that this pointer is using
		ReferenceCountedSingletonFactory<Interface>* factory() const
		{
			return factory_;
		}

	private:
		void EnsureAcquired()
		{
			Acquire();
			ASSERT(instance_ != NULL);
		}

		void Acquire()
		{
			// Since we're getting a singleton back, acquire is a noop if instance is
			// already populated.
			if (!instance_)
				instance_ = factory_->GetInstance();
		}

		Interface* instance_;
		ReferenceCountedSingletonFactory<Interface>* factory_;

		DISALLOW_IMPLICIT_CONSTRUCTORS(rcsf_ptr);
	};
}

#endif	// BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_